(function() {
	var _ach_state_arr;
	var _init_ach_state_arr = function() {
		_ach_state_arr = [];
		Object.keys(AchCon.STATE).forEach(function(key) {
			_ach_state_arr[AchCon.STATE[key]] = key;
		});
	};
	var skill = {
		save: function() {
			db.update(db_table_name, this._id, this);
		},
		destroy: function() {
			var bus = BusCon.get(this.info.bus_id);
			//返还库存
			this.info.goods_info.forEach(function(goods_info_and_num) {
				var goods = bus._getGoods(goods_info_and_num.goods._id, true);
				if (goods) {
					goods._returnNum(goods_info_and_num.num);
				}
			});
			db.remove(db_table_name, this._id);
		},
		show_info: function() {
			return this.info;
		},
		setInfo: function(info) {
			if (info.hasOwnProperty("pay_time")) {
				this.info.pay_time = info.pay_time;
			}
			if (info.hasOwnProperty("express_id")) {
				this.info.express_id = info.express_id;
			}
			this.save();
		},
		getDetail: function() {
			var result = $Object.clone(this);
			result.info.user = UserCon.get(this.info.user_id);
			result.info.recommender = UserCon.get(this.info.recommender_id);
			return result;
		},
		//非安全，用户确认订单
		//用户不再拥有修改的权限，商家也会收到订单
		_confirm: function() {
			var self = this;
			if (self.info.state !== AchCon.STATE.未确认) {
				throwCusError("订单无需重复确认")
			}
			if (self.info.use_space) {
				if (!self.info.space) {
					throwCusError("未指定用户使用空间");
				}
			} else {
				//非虚拟商品一定要指定用户收获地址
				if (!self.info.user_address && !self.isVirtual()) {
					throwCusError("未指定用户收获地址");
				}
			}
			//订单状态修改
			var pay_method = self.info.pay_method;
			if (pay_method === AchCon.METHOD.担保交易) {
				self.info.state = AchCon.STATE.ol未付款
			} else if (pay_method === AchCon.METHOD.货到付款) {
				if (self.isOnlyOlinePay()) {
					//虚拟商品交易
					throwCusError("该订单不能使用货到付款")
				} else {
					self.info.state = AchCon.STATE.未发货;
					//需要发货
					midEvent.emit("ach.need.shipment", self._id);
				}
			} else if (pay_method === AchCon.METHOD.财付通担保交易) {
				self.info.state = AchCon.STATE.ol未付款
			} else if (pay_method === AchCon.METHOD.支付宝网页支付) {
				self.info.state = AchCon.STATE.ol未付款
			} else if (pay_method === AchCon.METHOD.微信支付) {
				self.info.state = AchCon.STATE.ol未付款
			} else if (pay_method === AchCon.METHOD.当面付款) {
				self.info.state = AchCon.STATE.face未付款
			} else {
				throwCusError("未知的订单交易方式")
			}
			//通知商家收到订单，同时将订单加入商家的订单列表
			var bus = BusCon.get(this.info.bus_id);
			bus._receiveConfirmAch(this._id);
			midEvent.emit("ach.new", self._id, self.info.user_id, self.info.bus_id);
			self.save();
		},
		//非安全，设置订单快递单号
		_setExpressId: function(express_id) {
			this.info.express_id = express_id;
			this.save();
		},
		//将订单的状态流调整进入下一个
		_nextFlowStatus: function() {
			var state = +this.info.state;
			if (state || state == 0) {
				if (!_ach_state_arr) {
					_init_ach_state_arr();
				}
				//如果有下一个状态值，进入
				if (_ach_state_arr[state + 1]) {
					state += 1;
				}
			} else {
				throwCusError("未知的订单状态")
			}
			this.info.state = state;
			if (this.info.state === AchCon.STATE.ol未发货 || this.info.state === AchCon.STATE.未发货) {
				//记录发货时间，10天（autoConfirmFinishedAchTimeOut）后自动完结订单
				this.info.shipment_time = +new Date;
				//付款完成后需要发货
				midEvent.emit("ach.need.shipment", this._id);
			} else if (this.info.state === AchCon.STATE.ol未收货 || this.info.state === AchCon.STATE.已发货) {
				if (this.info.use_space) { //如果有当面消费，无需确认
					return this._nextFlowStatus();
				} else {
					//发货后通知用户收货
					midEvent.emit("ach.need.receiving", this._id);
				}
			} else if (
				this.info.state === AchCon.STATE.ol交易完成 ||
				this.info.state === AchCon.STATE.交易完成 ||
				this.info.state === AchCon.STATE.face交易完成
			) {
				//交易完成
				midEvent.emit("ach.deal.end", this._id);
			}
			midEvent.emit("ach.state.changed", this._id, this.info.user_id, this.info.bus_id, state);
			this.save();
			return state;
		},
		//获取货物暂存点信息
		getAchPoints: function(transportation_point) {
			return this.info.transportation_point;
		},
		//修改货物暂存点信息
		_updateAchPoints: function(transportation_point) {
			this.info.transportation_point = $Object.mix(this.info.transportation_point, transportation_point);
			this.save();
			return this.info.transportation_point;
		},
		//设置快递信息
		_setAchExpress: function(express_info) {
			var current_express_info = this.info.express_info || (this.info.express_info = {});
			current_express_info.company = express_info.company;
			current_express_info.num = express_info.num;
			this.save();
		},
		//商家自定义订单价格
		_customCash: function(cus_cash) {
			cus_cash = parseFloat(cus_cash) || 0;
			this.cus_cash = this.finally_cash = cus_cash;
			this.save();
		},
		changeAble: function() {
			var status_value = (+this.info.state);
			return status_value === AchCon.STATE.未确认;
		},
		//是否属于虚拟商品的订单（无需收货地址）
		//所有商品都属于虚拟商品时才行
		isVirtual: function() {
			var bus = BusCon.get(this.info.bus_id);
			return this.info.goods_info.every(function(goods_info) {
				return bus.getGoodsVirtual(goods_info.goods);
			});
		},
		//是否只能用在线支付
		//只要有一个商品不能用货到付款就全部要用在线支付
		isOnlyOlinePay: function() {
			if (this.info.is_only_online_pay !== undefined) {
				return this.info.is_only_online_pay;
			} else {
				var bus = BusCon.get(this.info.bus_id);
				return this.info.goods_info.some(function(goods_info) {
					return bus.getGoodsOnlyOlinePay(goods_info.goods);
				});
			}
		},
		//非安全，更改支付方式
		_updateAchPayMethod: function(new_pay_method) {
			var self = this;
			if (self.isOnlyOlinePay() && new_pay_method === AchCon.METHOD.货到付款) {
				throwCusError("该订单不能使用货到付款")
			}
			if (self.info.pay_method !== new_pay_method) {
				console.log(self.info.state);
				if (!self.changeAble()) {
					throwCusError("订单的支付方式已经无法更改");
				}
				self.info.pay_method = new_pay_method;
				self.save();
			}
			return new_pay_method;
		},
		//改变用户的收获地址
		_updateUserAddress: function(user_address) {
			if (!this.changeAble()) {
				throwCusError("订单的收获地址已经无法更改");
			}
			this.info.user_address = $Object.clone(user_address);
			if (this.info.user_address) {

				// 如果有对应的市代，添加市代回调BUFF
				var town = this.info.user_address.town
				var bus = BusCon.get(this.info.bus_id);
				var _MA_buff_id = this.info._MA_buff_id;
				bus.getMAList().some(MA => {
					// console.log("MA, ach.info.user_address", MA, this.info.user_address)
					if (MA.city_name === town) {
						// 添加BUFF
						var new_buff_config = {
							MA_user_id: MA.user_id
						};
						if (!_MA_buff_id) {
							var MA_buff = new BuffCon({
								name: "市代业绩",
								code_id: "商品交易完成增加市代业绩",
								info: new_buff_config
							});
							_MA_buff_id = this.info._MA_buff_id = MA_buff._id;
						} else {
							this._removeBuff(_MA_buff_id);
							MA_buff = BuffCon.get(_MA_buff_id);
							MA_buff.setConfig(new_buff_config);
						}
						this._addBuff(_MA_buff_id)
						return true
					}
				});
			}
			this.save();
			return this.info.user_address;
		},
		//改变使用空间
		_updateSpace: function(space) {
			if (!this.changeAble()) {
				throwCusError("订单的已经无法更改");
			}
			if (this.info.bus_id !== space.bus_id) {
				throwCusError("指定空间不属于当前商家");
			}
			this.info.space = $Object.clone(space);
			this.save();
			return this.info.space;
		},
		//改变使用空间
		_updateUseSpace: function(use_space) {
			if (!this.changeAble()) {
				throwCusError("订单的已经无法更改");
			}
			this.info.use_space = helper.boolean_parse(use_space);
			this.save();
			return this.info.space;
		},
		//非安全，使用BUFF后将BUFF信息详细记录下来
		_addBuff: function(buff_id) {
			var buff = BuffCon.get(buff_id);
			if (!buff) {
				throwCusError("找不到指定BUFF")
			}
			this._addBuffByInstance(buff);
		},
		_addBuffByInstance: function(buff) {
			(this.info.buffs || (this.info.buffs = [])).push($Object.clone(buff));
			this.save();
		},
		// 仅仅移除，不销毁BUFF
		_removeBuff: function(buff_id) {
			this.info.buffs = (this.info.buffs || []).filter(buff => {
				return buff._id === buff_id
			});
			this.save();
		},
		//返回针对订单的BUFF使用记录
		getBuffs: function() {
			return this.info.buffs || [];
		},
		getBuffsDetail: function(cb) {
			var result = [];
			this.getBuffs().forEach(function(buff) {
				if (buff) {
					buff = BuffCon.getInstance(buff);
					result.push(buff);
				}
			});
			return result;
		},
		//重新初始化花费额度
		_initCash: function() {
			var sou_cash = 0;
			var express_cash = 0;
			var total_goods_num = 0;
			// var sou_cash = this.cus_cash || 0;
			var _env = BuffCon.env.inCashPay;
			// if (sou_cash) { //如果有自定义价格，使用自定义价格
			// 	this.cash = this.sou_cash = sou_cash;
			// 	this.save();
			// 	return;
			// }
			//开始运行buff
			this.info.goods_info.forEach(function(goods_info) {
				var goods_id = goods_info.goods._id;
				var num = +goods_info.num;
				var other_args = {
					goods_id: goods_id,
					num: num
				};
				var goods = GoodsCon.get(goods_id);
				if (!goods) {
					throwCusError("商品已被删除无法获取商品价格");
				}
				sou_cash += goods.getCash(_env, "ach_getCash", other_args) * num;
				express_cash += goods.express_price * num;
				total_goods_num += num;
			});
			this.cash = this.sou_cash = sou_cash;

			this.sou_express_cash = express_cash;
			this.total_goods_num = total_goods_num;
			this.bind_acc && (this.cash -= this.bind_acc);
			this.bus_user_money && (this.cash -= this.bus_user_money);
			this.save();
		},
		//获取最终花费额度，不包含运费
		getCash: function() {
			//计算基础消费额
			var ach_id = this._id;
			//订单状态
			var _env = BuffCon.env.inCashPay;
			if (this.info.pay_method === AchCon.METHOD.担保交易) {
				_env = BuffCon.env.inOnlinePayAch;
			}

			if (this.info.state === AchCon.STATE.未确认) { //如果订单已经确认不可修改，无需再获取基本订单数据
				//否则订单的基础金额、运费都会发生改变
				this._initCash();
			}
			//重置金额

			this.express_cash = this.sou_express_cash || (this.sou_express_cash = 0);
			if (this.express_cash > 0) { //需要运费，判断是否可以免运费
				var bus = BusCon.get(this.info.bus_id);
				if (bus.info.express_free_total_price && bus.info.express_free_total_price <= this.sou_cash) {
					this.express_cash = 0;
				} else if (bus.info.express_free_total_num && bus.info.express_free_total_num <= this.total_goods_num) {
					this.express_cash = 0;
				}
			}

			//运行BUFF
			this.emitBuffs(_env, "ach_getCash")

			this.sou_finally_cash = this.cash + this.express_cash;
			this.finally_cash = this.cus_cash || this.sou_finally_cash;
			return this.cash;
		},
		//代码片段获取订单真正需要花费的金额
		_getAchCash: function() {
			return this.finally_cash;
		},
		//运作BUFF
		emitBuffs: function(buffEnv, callBy) {
			// return achBuffCB._emitBuffCallBack(eventName,this._id);
			var buffs = this.getBuffsDetail();

			var emit_arg = {
				env: buffEnv,
				callBy: callBy,
				ach_id: this._id,
				user_id: this.info.user_id,
				bus_id: this.info.bus_id,
				recommender_id: this.info.recommender_id
			};
			buffs.forEach(function(buff) {
				buff.emit(emit_arg)
			});

			this.info.goods_info.forEach(function(goods_info) {
				emit_arg.goods_info = goods_info;
				emit_arg.goods_id = goods_info.goods._id;
				goods_info.buffs.forEach(function(buff) {
					buff = BuffCon.getInstance(buff);
					buff.emit(emit_arg);
				});
			});
		},
		//BUFF需要回调的，统一注册
		registerBuffCallBack: function(eventName, buff_id, cb) {
			return achBuffCB._addBuffCallBack(eventName, this._id, buff_id, cb);
		},
		//非安全，取消订单
		//在线支付的订单需要在付款前取消
		//货到付款订单需要在商家发货前取消
		_cancel: function() {
			//未确认订单，由用户取消，与商家无关
			var ach_id = this._id;
			if (this.info.state === AchCon.STATE.未确认) {
				var _remove_form_bus = false;
			} else if (this.info.state === AchCon.STATE.ol未付款 || this.info.state === AchCon.STATE.未发货 || this.info.state === AchCon.STATE.face未付款) {
				var _remove_form_bus = true;
			} else {
				var _throw_state_error = true;
			}

			if (_throw_state_error) {
				throwCusError("订单所处的状态无法进行“取消订单”的操作");
			} else {
				midEvent.emit("ach.before_cancel", ach_id, this.info.user_id, this.info.bus_id);

				var user = UserCon.get(this.info.user_id);
				user._removeAch(ach_id);

				//退还抵扣金额
				if (this.bus_user_money) {
					var bus_user = user.getBusUser_by_busId(this.info.bus_id);
					bus_user._unUseMoney(this.bus_user_money, "订单“" + this._id + "”取消退款");
				}

				//退还优惠券
				if (this.ticket_id) {
					ticket = TicketCon.get(this.ticket_id);
					if (ticket) {
						ticket._unUseForAch(this._id);
					}
				}

				if (_remove_form_bus) {
					var bus = BusCon.get(this.info.bus_id);
					bus._removeAch(ach_id);
				}

				this.destroy();
				midEvent.emit("ach.cancel", ach_id, this.info.user_id, this.info.bus_id);
			}
		},
		//非安全，为订单中的商品添加评价功能
		_evalGoods: function(evaluations) {
			var user = UserCon.get(this.info.user_id);
			var goods_info = this.info.goods_info;
			evaluations.forEach(function(evaluation_info) {
				var goods_id = evaluation_info.goods_id;
				var current_goods_info;
				goods_info.every(function(goods_info) {
					if (goods_info.goods._id === goods_id) {
						current_goods_info = goods_info;
					} else {
						return true;
					}
				});
				if (!current_goods_info) {
					throwCusError("无法匹配到对应的商品进行评价")
				}
				if (!current_goods_info.eval_id) {
					var content = String(evaluation_info.content || "").trim();
					if (!content) {
						throwCusError("评价内容不可为空")
					}
					var eval_id = user.addEvaluation(
						goods_id,
						evaluation_info.star_num,
						content,
						evaluation_info.isAny
					);
					current_goods_info.eval_id = eval_id;
				} else {
					// var eval = EvalCon.get(current_goods_info.eval._id);
					throwCusError("商品已经绑定过评价")
				}
			});
			this.save();
		},
		//判断订单已经
		isFinishAch: function() {
			var state = this.info.state;
			return state === AchCon.STATE.ol交易完成 ||
				state === AchCon.STATE.ol已评价 ||
				state === AchCon.STATE.交易完成 ||
				state === AchCon.STATE.已评价 ||
				state === AchCon.STATE.face交易完成 ||
				state === AchCon.STATE.face已评价;
		},
		//判断订单是否完成了支付
		isEndPay: function() {
			var state = this.info.state;
			return this.isFinishAch() || state === AchCon.STATE.ol未发货 ||
				state === AchCon.STATE.ol未发货;
		}
	}
	module.exports = skill.multiInherits(
		require("./skill.coupon"),
		require("./skill.ticket"),
		require("./skill.card"),
		require("./skill.bus_user_bind"),
		require("./skill.bus_user")
	);

	var db = require("../db/index");
	var config = require("../_include/config");
	var db_table_name = config.dbname.ach;
	var db_id_prefix = config.dbIdPrefix.ach;
	var TicketCon = require("../ticket/_con");
	var AchCon = require("./_con");
	var BusCon = require("../bus/_con");
	var UserCon = require("../user/_con");
	var EvalCon = require("../eval/_con");
	var BuffCon = require("../buff/_con");
	var GoodsCon = require("../goods/_con");
	var UserAddressCon = require("../user_address/_con");
	var buffCode = require("../buff/buff_code");
	var achBuffCB = require("../ach/ach_buff_cb");
	var helper = require("../_include/helper");
	var $Object = require("../_include/$.Object");
	var midEvent = require("../../middleware/index");

})();